using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace MicrosoftFrance.MCS.EPM2007
{
    class PSIQueueSystem
    {
        // Wait for the job to finish.
        // Outputs job status to the console.
        static public void WaitForQueue(QueueSystemWS.QueueSystem q, Guid jobId)
        {
            QueueSystemWS.JobState jobState;
            const int QUEUE_WAIT_TIME = 1; // one second
            bool jobDone = false;
            string xmlError = string.Empty;
            int wait = 0;

            wait = q.GetJobWaitTime(jobId);
            Console.Write("Waiting on queue. Estimate: {0} seconds.\r\n ", wait);

            // - Wait until it is done.
            do
            {
                // - Get the job state
                jobState = q.GetJobCompletionState(jobId, out xmlError);

                if (jobState == QueueSystemWS.JobState.Success)
                {
                    jobDone = true;
                }
                else
                {
                    if (jobState == QueueSystemWS.JobState.Unknown
                    || jobState == QueueSystemWS.JobState.Failed
                    || jobState == QueueSystemWS.JobState.FailedNotBlocking
                    || jobState == QueueSystemWS.JobState.CorrelationBlocked
                    || jobState == QueueSystemWS.JobState.Canceled)
                    {
                        // If the job failed, error out
                        throw (new ApplicationException("Queue request " + jobState + " for Job ID " + jobId + ".\r\n" + xmlError));
                    }
                    else
                    {
                        //Console.WriteLine("Job State: " + jobState + " for Job ID: " + jobId);
                        Console.Write("~");
                        Thread.Sleep(QUEUE_WAIT_TIME * 1000);
                    }
                }
            }
            while (!jobDone);
            Console.Write("\r\n");
        }

        private static bool CheckQueueStatus(Guid[] projectGuids)
        {
            QueueSystemWS.JobState[] JobStates = 
                { QueueSystemWS.JobState.ReadyForProcessing, QueueSystemWS.JobState.Processing };
            QueueSystemWS.QueueMsgType[] MsgTypes = { QueueSystemWS.QueueMsgType.ProjectDelete };

            bool inProcess = true;
            DateTime startTime = DateTime.Now;
            DateTime now = DateTime.Now;
            DateTime lastWeek = now - new TimeSpan(7, 0, 0, 0);
            while (inProcess)
            {
                QueueSystemWS.QueueStatusDataSet QSDS =
                    Program.queueSystem.ReadProjectJobStatus(projectGuids, MsgTypes, JobStates,
                        lastWeek, now, -1, false, QueueSystemWS.SortColumn.Undefined,
                        QueueSystemWS.SortOrder.Undefined);
                if (QSDS.Tables[0].Rows.Count == 0)
                {
                    return true;
                }

                DateTime endTime = DateTime.Now;
                TimeSpan span = endTime.Subtract(startTime);
                if (span.Seconds > 20) //Wait for only 20 secs - and then bail out.
                {
                    Console.Write("Something is wrong in the Queue. Check/Clear the queue and then redo your action");
                    return false;
                }
            }
            return true;
        }

        public static void ClearAllMyFailedTSJobs()
        {
            TimeSpan ts = new TimeSpan(6, 0, 0);
            QueueSystemWS.JobState[] jobStates = { QueueSystemWS.JobState.Failed };
            QueueSystemWS.QueueMsgType[] msgTypes = { QueueSystemWS.QueueMsgType.TimesheetDelete, QueueSystemWS.QueueMsgType.TimesheetSubmit, QueueSystemWS.QueueMsgType.TimesheetUpdate };
            QueueSystemWS.QueueStatusDataSet qsDS = Program.queueSystem.ReadMyJobStatus(msgTypes, jobStates, DateTime.Now.Subtract(ts), DateTime.Now, 1000, false, MicrosoftFrance.MCS.EPM2007.QueueSystemWS.SortColumn.QueueEntryTime, MicrosoftFrance.MCS.EPM2007.QueueSystemWS.SortOrder.Descending);

            for (int i = 0; i < qsDS.Status.Count; i++)
            {
                Program.queueSystem.CancelJob(qsDS.Status[i].JobGUID, true, true);
            }
        }

        public static int GetJobWaitTime(Guid jobId)
        {
            return Program.queueSystem.GetJobWaitTime(jobId);
        }
    }
}
